#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_pwm.h"
#include "hi_io.h"
#include "hi_pwm.h"
#include "hi_time.h"

// --- 音乐(蜂鸣器)部分 (GPIO 11 / PWM2) ---

// 音符频率分频值（40MHz时钟）
static const uint16_t g_tuneFreqs[] = {
    0,
    38223, // 1 高音Do
    34052, // 2 高音Re
    30338, // 3 高音Mi
    28635, // 4 高音Fa
    25511, // 5 高音So
    22728, // 6 高音La
    20249, // 7 高音Si
    51021, // 8 中音So
};

// 《两只老虎》简谱
static const uint8_t g_scoreNotes[] = {
    1, 2, 3, 1, 1, 2, 3, 1, 3, 4, 5, 3, 4, 5,
    5, 6, 5, 4, 3, 1, 5, 6, 5, 4, 3, 1, 1, 8, 1, 1, 8, 1,
};

// 音符时值（单位：拍）
static const uint8_t g_scoreDurations[] = {
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 8,
    3, 1, 3, 1, 4, 4, 3, 1, 3, 1, 4, 4, 4, 4, 8, 4, 4, 8,
};

// 蜂鸣器初始化函数 (GPIO 11 / PWM2)
static void beepInit(void) {
    hi_gpio_init(); 
    hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_PWM2_OUT); 
    hi_pwm_init(HI_PWM_PORT_PWM2); 
    hi_pwm_set_clock(PWM_CLK_XTAL); 
}

// 蜂鸣器播放任务
static void beepSingTask(void *arg) {
    (void)arg;
    beepInit();

    while(1) // 增加一个外层循环，让音乐重复播放
    {
        for (size_t i = 0; i < sizeof(g_scoreNotes) / sizeof(g_scoreNotes[0]); i++) {
            uint8_t note = g_scoreNotes[i];
            
            if (note >= (sizeof(g_tuneFreqs) / sizeof(g_tuneFreqs[0]))) {
                printf("Error: Note index %d out of bounds!\n", note);
                continue;
            }
            
            uint16_t freqDiv = g_tuneFreqs[note];
            uint32_t duration = g_scoreDurations[i] * (125 * 1000);

            if (note > 0)
            {
                hi_pwm_start(HI_PWM_PORT_PWM2, freqDiv / 2, freqDiv);
                hi_udelay(duration);
                hi_pwm_stop(HI_PWM_PORT_PWM2);
            } else {
                hi_udelay(duration);
            }
            
            hi_udelay(50000);
        }
        osDelay(1000); // 播放完一次后，休息1秒
    }
}


// --- 呼吸灯部分 (GPIO 10 / PWM1) ---

#define BREATH_PWM_PORT HI_PWM_PORT_PWM1
#define BREATH_PWM_FREQ 2000  // 设置一个固定的高频率 (2000Hz)
#define BREATH_STEP 20        // 亮度变化的步长
#define BREATH_DELAY 10000    // 每一步变化的延迟 (10ms)

// --- 新增：呼吸灯初始化函数 ---
static void breathingLightInit(void) {
    // GPIO 10 复用为 PWM1
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_PWM1_OUT);
    hi_pwm_init(BREATH_PWM_PORT);
    // (时钟源在beepInit里已经设置为XTAL，这里无需重复设置)
}

// --- 新增：呼吸灯任务 ---
static void breathingLightTask(void *arg) {
    (void)arg;
    breathingLightInit();
    uint16_t duty = 0; // 占空比

    while (1) 
    {
        // 1. 渐亮 (Fade In)
        // 将占空比从 0 增加到 BREATH_PWM_FREQ
        for (duty = 0; duty < BREATH_PWM_FREQ; duty += BREATH_STEP) {
            hi_pwm_start(BREATH_PWM_PORT, duty, BREATH_PWM_FREQ);
            hi_udelay(BREATH_DELAY);
        }
        // 确保达到最亮
        hi_pwm_start(BREATH_PWM_PORT, BREATH_PWM_FREQ, BREATH_PWM_FREQ);

        // 2. 渐暗 (Fade Out)
        // 将占空比从 BREATH_PWM_FREQ 减小到 0
        for (duty = BREATH_PWM_FREQ; duty > BREATH_STEP; duty -= BREATH_STEP) {
            hi_pwm_start(BREATH_PWM_PORT, duty, BREATH_PWM_FREQ);
            hi_udelay(BREATH_DELAY);
        }
        // 确保完全熄灭
        hi_pwm_stop(BREATH_PWM_PORT);
        hi_udelay(BREATH_DELAY * 10); // 灭灯时多停留一会儿
    }
}


// --- 任务入口修改 ---
// 【修改】 BeepEntry 现在会启动两个任务
static void BeepEntry(void) {
    // 1. 创建蜂鸣器音乐任务
    osThreadAttr_t beepAttr = {
        .name = "beepSingTask",
        .stack_size = 4096,
        .priority = osPriorityNormal,
    };
    if (osThreadNew(beepSingTask, NULL, &beepAttr) == NULL) {
        printf("Failed to create beepSingTask!\n");
    }

    // 2. 创建呼吸灯任务
    osThreadAttr_t lightAttr = {
        .name = "breathingLightTask",
        .stack_size = 2048, // 呼吸灯任务简单，栈可以小一点
        .priority = osPriorityNormal,
    };
    if (osThreadNew(breathingLightTask, NULL, &lightAttr) == NULL) {
        printf("Failed to create breathingLightTask!\n");
    }
}

SYS_RUN(BeepEntry);